using System;
using System.Collections.Generic;

using Pegasus.Diagnostics;
using Pegasus.Runtime.Serialization;

namespace Pegasus.Workflow.Service.DefaultServices
{
	/// <summary>
	/// Does not persist the objects, leaves them in memory
	/// </summary>
	public class NullPersistenceService : WorkflowPersistenceService
	{
		// Local Instance Values
		private object m_lock = new object();
		private Dictionary<int, string> m_memoryXmlTable = new Dictionary<int, string>();
		private int m_nextWorkflowId = 1;

		/// <summary>
		/// Initializes a new instance of the <see cref="T:NullPersistenceService"/> class.
		/// </summary>
		public NullPersistenceService()
		{
		}

		/// <summary>
		/// Starts this instance of the service.
		/// </summary>
		/// <param name="workflowService"></param>
		public override void Start( WorkflowService workflowService )
		{
			base.Start( workflowService );

			lock( m_lock )
			{
				m_nextWorkflowId = 1;
				m_memoryXmlTable.Clear();
			}
		}

		/// <summary>
		/// Stops this instance of the service.
		/// </summary>
		public override void Stop()
		{
			base.Stop();

			lock( m_lock )
			{
				m_nextWorkflowId = 1;
				m_memoryXmlTable.Clear();
			}
		}

		/// <summary>
		/// Registers a new workflow context with the persistence service.
		/// </summary>
		/// <param name="context">The context.</param>
		/// <returns></returns>
		protected override int OnRegisterNewWorkflowContext( WorkflowContext context )
		{
			int workflowId = -1;

			lock( m_lock )
			{
				workflowId = m_nextWorkflowId++;
				InitializeNewContext( context, workflowId );

				string contextXml = SerializationHelper.ObjectToXml( context );
				m_memoryXmlTable.Add( workflowId, contextXml );
			}

			return workflowId;
		}

		/// <summary>
		/// Saves the workflow context.
		/// </summary>
		/// <param name="context">The context.</param>
		/// <param name="unlock">if set to <c>true</c> [unlock].</param>
		protected override void OnSaveWorkflowContext( WorkflowContext context, bool unlock )
		{
			lock( m_lock )
			{
				string contextXml = SerializationHelper.ObjectToXml( context );
				m_memoryXmlTable[ context.WorkflowId ] = contextXml;

				if( unlock )
				{
					OnReleaseWorkflowContext( context );
				}
			}
		}

		/// <summary>
		/// Loads the workflow context.
		/// </summary>
		/// <param name="workflowId">The workflow id.</param>
		/// <param name="readOnly">if set to <c>true</c> [read only].</param>
		/// <returns></returns>
		protected override WorkflowContext OnLoadWorkflowContext( int workflowId, bool readOnly )
		{
			WorkflowContext context = null;

			lock( m_lock )
			{
				if( m_memoryXmlTable.ContainsKey( workflowId ) )
				{
					context = (WorkflowContext) SerializationHelper.XmlToObject( m_memoryXmlTable[ workflowId ] );
					InitializeExistingContext( workflowId, context, readOnly );
				}
				else
				{
					throw new WorkflowNotFoundException( workflowId );
				}
			}

			return context;
		}

		/// <summary>
		/// Releases the workflow context.
		/// </summary>
		/// <param name="context">The context.</param>
		protected override void OnReleaseWorkflowContext( WorkflowContext context )
		{
			lock( m_lock )
			{
				SetContextAsReadOnly( context );
			}
		}
	}
}
